#include <soar.h>

#include "common.h"

#define	DB_CONNECT_NUM		3	

struct thrd_ctl
{
    unsigned int thrd_id;
	int thrd_idx;
    MYSQL db;
};
static struct thrd_ctl a_thrd_ctl[DB_CONNECT_NUM];

int insert(struct thrd_ctl *thrd_ctl)
{/*{{{*/
    char buf[BUFFER_SIZE];
    int res;

    printf("Thrd(%d) %s\n", thrd_idx, __func__);

    sprintf(buf,
            "insert into my_emp "
            "values(%d, sysdate(), '职员100', '8', 34, '云南')",
            (thrd_idx+1)*100);
    printf("Thrd(%d) SQL: %s\n", thrd_idx, buf);
    res=mysqlc_exec_ex(thrd_ctl->db, buf);
    if(res != MY_OK)
    {
        printf("Thrd(%d) %s: fail, sqlcode:%d\n",
                thrd_idx, __func__, res); 
        return(-1);
    }

    printf("Thrd(%d) %s succeed\n", thrd_idx, __func__);
    printf("==================================================\n");

    return(0);
}/*}}}*/

int delete(struct thrd_ctl *thrd_ctl)
{/*{{{*/
    char buf[BUFFER_SIZE];
    int res;

    printf("Thrd(%d) %s\n", thrd_idx, __func__);

    sprintf(buf,
            "delete from my_emp where empno=%d",
            (thrd_idx+1)*100);
    res=mysqlc_exec_ex(thrd_ctl->db, buf);
    if(res != MY_OK)
    {
        printf("Thrd(%d) %s: fail, sqlcode:%d\n",
                thrd_idx, __func__, res); 
        return(-1);
    }

    printf("Thrd(%d) %s succeed\n", thrd_idx, __func__);
    printf("==================================================\n");

    return(0);
}/*}}}*/

int update()
{/*{{{*/
    char buf[BUFFER_SIZE];
    int result;

    printf("update\n");

    sprintf(buf, "update my_emp set upd_ts=%s where empno=%d",
#if defined _DBC_ORACLE
            "sysdate"
#elif defined _DBC_MYSQL
            "now()"
#elif defined _DBC_PGSQL
            "sysdate"
#endif
        , random_int(1, 10));
    result=dbc_exec(buf);
    if(result != DBC_OK && result != DBC_NO_DATA_FOUND)
    {
        printf("错误，sqlcode:%d\n",
            result); 
        return(-1);
    }
    if(result == DBC_NO_DATA_FOUND)
    {
        printf("未找到记录\n"); 
    }

    printf("成功\n");
    printf("==================================================\n");

    return(0);
}/*}}}*/

int query1()
{/*{{{*/
    struct dbc_query_result_set result_set;
    int request_row_num;
    struct my_emp my_emp;
    int row_index;
    char buf[BUFFER_SIZE];
    int result;

    printf("query1\n");

    sprintf(buf, "select * from my_emp where age>10 order by empno asc");
    printf("SQL: %s\n", buf);
    request_row_num=8;
    result=dbc_query(buf, request_row_num,
        &result_set);
    if(result != DBC_OK)
    {
        printf("错误，sqlcode:%d\n", result);
        return(-1);
    }
    printf("结果：\n");
    for(row_index=0; row_index<result_set.row_num; row_index++)
    {
        DBC_COL_EXPORT_LLONG(&result_set, row_index, 0, my_emp.empno);
        DBC_COL_EXPORT_DATE(&result_set, row_index, 1,
            my_emp.upd_ts);
        DBC_COL_EXPORT_CHAR(&result_set, row_index, 2,
            my_emp.name);
        DBC_COL_EXPORT_CHAR(&result_set, row_index, 3,
            my_emp.duty);
        DBC_COL_EXPORT_INT(&result_set, row_index, 4,
            my_emp.age);
        printf("%lld|%s|%s|%s|%d\n", my_emp.empno, my_emp.upd_ts,
            my_emp.name, my_emp.duty, my_emp.age);
    }
    if(result_set.query_flag == QUERY_BOTTOM)
        printf("查询到底\n");
    else
        printf("查询中途\n");
    dbc_query_free(&result_set);

    printf("成功\n");
    printf("==================================================\n");

    return(0);
}/*}}}*/

int query2()
{/*{{{*/
    struct dbc_query_result_set result_set;
    char buf[BUFFER_SIZE];
    int result;
    int count, sum;

    printf("query2\n");

    sprintf(buf, "select count(*),sum(age) from my_emp where age>20");
    printf("SQL: %s\n", buf);
    result=dbc_query(buf, -1, &result_set);
    if(result != DBC_OK)
    {
        printf("错误, sqlcode:%d\n",
            result);
        return(-1);
    }
    DBC_COL_EXPORT_INT(&result_set, 0, 0, count);
    DBC_COL_EXPORT_INT(&result_set, 0, 1, sum);
    printf("结果：%d %d\n", count, sum);
    dbc_query_free(&result_set);

    printf("成功\n");
    printf("==================================================\n");

    return(0);
}/*}}}*/

int query3()
{/*{{{*/
    struct dbc_query_result_set result_set;
    int row_index;
    struct my_emp my_emp;
    int count;
    char buf[BUFFER_SIZE];
    int result;

    printf("query3\n");

    sprintf(buf, "select duty,count(*) from my_emp where duty in ('1','2','3') group by duty order by duty desc");
    printf("SQL: %s\n", buf);
    result=dbc_query(buf, -1, &result_set);
    if(result != DBC_OK)
    {
        printf("错误, sqlcode:%d\n",
            result);
        return(-1);
    }

    printf("结果：\n");
    for(row_index=0; row_index<result_set.row_num; row_index++)
    {
        DBC_COL_EXPORT_CHAR(&result_set, row_index, 0,
            my_emp.duty);
        DBC_COL_EXPORT_INT(&result_set, row_index, 1, count);
        printf("%s|%d\n", my_emp.duty, count);
    }
    dbc_query_free(&result_set);

    printf("成功\n");
    printf("==================================================\n");

    return(0);
}/*}}}*/

int query4()
{/*{{{*/
    struct dbc_query_result_set result_set;
    struct my_emp my_emp;
    struct my_salary my_salary;
    int row_index;
    char buf[BUFFER_SIZE];
    int result;

    printf("query4\n");

    sprintf(buf, "select a.empno,a.name,b.salary from my_emp a, my_salary b where a.empno=b.empno order by a.empno asc");
    printf("SQL: %s\n", buf);
    result=dbc_query(buf, -1, &result_set);
    if(result != DBC_OK)
    {
        printf("query4: dbc_query fail, sqlcode:%d\n",
            result);
        return(-1);
    }
    printf("结果：\n");
    for(row_index=0; row_index<result_set.row_num; row_index++)
    {
        DBC_COL_EXPORT_LLONG(&result_set, row_index, 0,
            my_emp.empno);
        DBC_COL_EXPORT_CHAR(&result_set, row_index, 1,
            my_emp.name);
        DBC_COL_EXPORT_DOUBLE(&result_set, row_index, 2,
            my_salary.salary);
        printf("%lld|%s|%.2f\n", my_emp.empno, my_emp.name,
            my_salary.salary);
    }
    dbc_query_free(&result_set);

    printf("成功\n");
    printf("==================================================\n");

    return(0);
}/*}}}*/

int sequence()
{/*{{{*/
    char buf[BUFFER_SIZE];
    int result;
    long nextval;

    printf("sequence\n");

    sprintf(buf, "seq_my_emp");
    printf("SQL: nextval of %s\n", buf);
    result=dbc_sequence_nextval(buf, &nextval);
    if(result != DBC_OK)
    {
        printf("sequence: dbc_sequence_nextval fail, sqlcode:%d\n",
            result);
        return(-1);
    }
    printf("结果：%ld\n", nextval);

    printf("成功\n");
    printf("==================================================\n");

    return(0);
}/*}}}*/

void *thrd_func(struct thrd_ctl *thrd_ctl)
{/*{{{*/
    mysqlc_begin_ex(thrd_ctl->db);

    if(
            insert(thrd_ctl)
            || delete(thrd_ctl)
            || update(thrd_ctl)
            || query1(thrd_ctl)
            || query2(thrd_ctl)
            || query3(thrd_ctl)
            || query4(thrd_ctl)
            )
    {
        mysqlc_rollback_ex(thrd_ctl->db);
    }
    else
    {
        mysqlc_commit_ex(thrd_ctl->db);
    }

    mysqlc_disconnect_ex(thrd_ctl->db);
    return(NULL);
}/*}}}*/

int main(int argc, char *argv[])
{/*{{{*/
    int thrd_idx;
    int res;

    mysqlc_init();

    for(thrd_idx=0; thrd_idx<DB_CONNECT_NUM; thrd_idx++)
    {
        if((res=mysql_connect_ex("dbuser", "dbuser", NULL, NULL,
                        &a_thrd_ctl[thrd_idx].db))!= ORA_OK)
        {
            printf("connect(%d) fail, sqlcode:%d\n",
                    thrd_idx, res); 
            return(-1);
        }
        a_thrd_ctl[thrd_idx].thrd_idx=thrd_idx;
        if(thrd_create((THRD_FUNC_T)thrd_func,
                    (void *)&a_thrd_ctl[thrd_idx],
                    0, &a_thrd_ctl[thrd_idx].thrd_id))
        {
            printf("Thread create fail\n");
            return(-1);
        }
    }
    for(thrd_idx=0; thrd_idx<DB_CONNECT_NUM; thrd_idx++)
    {
        thrd_join(a_thrd_ctl[thrd_idx].thrd_id);
    }

    mysqlc_clean();

    return(0);
}/*}}}*/
